package de.uni_mannheim.informatik.ai.dame_ai.dame.domain;

import java.util.ArrayList;
import java.util.ListIterator;
import java.util.Observable;
import java.util.Observer;

import de.uni_mannheim.informatik.ai.dame_ai.main.application.GameSettings;


public class Checkers extends Observable {
	protected Board board = new Board();
	protected Player[] players;
	// protected Piece[] piecesStatus = new Piece[Board.BOARDSQUARES];
	protected Player currentPlayer;
	protected GameLogic gamelogic = new GameLogic();
	protected boolean selectionPossible = true;
	protected int selectedPiece = -1;
	protected ArrayList<Observer> observers;
	private boolean changed = false;
	private boolean gameOver = false;
	private GameSettings data;
	

	public Checkers(Player[] players, GameSettings data) {
		this.data = data;
		initPlayer(players);
		observers = new ArrayList<Observer>();
	}

	@Override
	protected synchronized void clearChanged() {
		// TODO Auto-generated method stub
		changed = false;
	}

	@Override
	protected synchronized void setChanged() {
		// TODO Auto-generated method stub
		changed = true;
	}

	@Override
	public synchronized boolean hasChanged() {
		// TODO Auto-generated method stub
		return changed;
	}

	@Override
	public synchronized void addObserver(Observer o) {
		// TODO Auto-generated method stub
		observers.add(o);
		notifyObservers();
	}
	synchronized public void setGameStatus(GameStatus status){
		this.board = status.getBoard();
		this.currentPlayer = status.getCurrentPlayer();
		this.selectedPiece = status.getSelectedPiece();
		this.selectionPossible = status.isSelectionPossible();
		this.gameOver = status.isGameOver();
		notifyObservers();
	}
	@Override
	public void notifyObservers() {
		ListIterator<Observer> it = observers.listIterator();
		System.out.println("Creating new GameStatus currentPlayer: "
				+ currentPlayer);
		GameStatus newStatus = new GameStatus(board, currentPlayer,
				selectionPossible, selectedPiece, data);
		newStatus.setGameOver(gameOver);
		while (it.hasNext()) {
			it.next().update(this, newStatus);
		}
	}
	public boolean checkIfPlayerLost(Player player){
		Move[] possibleMoves = GameLogic.getAllPossibleMoves(board.getPiecesStatus(), player);
		if(possibleMoves.length >0){
			return false;
		} else return true;
	}
	private void initPlayer(Player[] players) {
		this.players = players;
		currentPlayer = this.players[0];
		
	}

	/**
	 * Method executes Move
	 * 
	 * @param move
	 *            The move to be made
	 */
	public synchronized boolean makeMove(Move move) {
		System.out.println("Checking if move is possible again");
		if (GameLogic.isPossible(board.getPiecesStatus(), move)) {
			System.out.println("Executing move");
			System.out.println("CurrentPlayer: " + currentPlayer);
			int newPlayer = GameLogic.executeMove(move, board, currentPlayer
					.getNumber());

			if (newPlayer == currentPlayer.getNumber()) {
				selectionPossible = false;
				selectedPiece = move.targetPosition;
			} else {
				currentPlayer = players[newPlayer];
				selectionPossible = true;
				selectedPiece = -1;
			}
			System.out.println("CurrentPlayer: " + currentPlayer);
			gameOver = checkIfPlayerLost(currentPlayer);
			notifyObservers();
			return true;
		}else return false;
	}

	/**
	 * Template for the game end
	 */
	public synchronized void endCheckersGame() {

	}

	/**
	 * This methods selected on piece
	 * 
	 * @param position
	 *            The position on the board of the to be selected piece
	 */
	public synchronized void selectPiece(int position) {
		System.out.println("Making Selection");
		if (selectionPossible(position)) {
			Move[] possibleMoves = gamelogic.getPossibleMoves(board.getPiecesStatus(), position);
			Move[] jumpMoves = gamelogic.getAllPossibleJumpMoves(possibleMoves);
			if(jumpMoves.length>0) possibleMoves = jumpMoves;
			if (gamelogic.selectPiece(possibleMoves, board.getBoard())) {

				selectedPiece = position;
			}
		}
		notifyObservers();
	}

	public boolean selectionPossible(int position) {
		boolean result = false;
		short type = board.getPiecesStatus()[position].getType();
		if (type == Piece.EMPTY)
			result= false;
		else if (currentPlayer.getColor() == Player.BLACK) {
			if (type == Piece.BLACK || type == Piece.BLACKDAME) {
				result = true;
			} else
				result = false;
		} else {
			if (type == Piece.WHITE || type == Piece.WHITEDAME) {
				result = true;
			} else
				result = false;
		}
		if(result){
			System.out.println("Checking if jumps are available");
			Move[] jumpMoves = GameLogic.getAllPossibleJumpMoves(board.getPiecesStatus(), currentPlayer);
			System.out.println("Size: "+jumpMoves.length);
			if(jumpMoves.length >0)result = false;
			for(Move move : jumpMoves){
				if(move.getFromPos() == position)result = true;
			}
		}
		return result;
	}

	public Board getBoard() {
		return board;
	}

	public Player[] getPlayers() {
		return players;
	}

	/**
	 * Deselect all Pieces
	 */
	public synchronized void deselect() {
		if (selectionPossible)
			gamelogic.deselect(board.getBoard());
		selectedPiece = -1;
		notifyObservers();
	}

	public Player getCurrentPlayer() {
		return currentPlayer;
	}

	public GameLogic getGamelogic() {
		return gamelogic;
	}

}
